package josex

import (
	"errors"
	ecdsax "gitee.com/zackeus/go-boot/josex/ecdsa"
	"gitee.com/zackeus/go-boot/josex/ed25519"
	"gitee.com/zackeus/go-boot/josex/hmac"
	rsax "gitee.com/zackeus/go-boot/josex/rsa"
	"github.com/go-jose/go-jose/v4"
)

// GeneratePemKey 根据算法生成密钥对
func GeneratePemKey(alg jose.SignatureAlgorithm) (privKeyPEM []byte, pubKeyPEM []byte, err error) {
	switch alg {
	case jose.EdDSA:
		return ed25519.GenerateEdDSAPem()
	case jose.HS256, jose.HS384, jose.HS512:
		key, err := hmac.GenerateHMACPem(alg)
		/* 对称算法没有公钥 */
		return key, key, err
	case jose.RS256, jose.RS384, jose.RS512:
		return rsax.GenerateRSAPem(alg)
	case jose.ES256, jose.ES384, jose.ES512:
		return ecdsax.GenerateECDSAPem(alg)
	case jose.PS256, jose.PS384, jose.PS512:
		/* PS 系列算法使用的是 RSA 密钥 */
		return rsax.GenerateRSAPem(alg)
	default:
		return nil, nil, errors.New("unsupported algorithm")
	}
}

// LoadPublicKey 加载 PEM 格式的公钥
// It must have one of these types:
//   - ed25519.PublicKey
//   - *ecdsa.PublicKey
//   - *rsa.PublicKey
//   - []byte (a symmetric key)
func LoadPublicKey(alg jose.SignatureAlgorithm, pubPemBytes []byte) (any, error) {
	switch alg {
	case jose.EdDSA:
		return ed25519.LoadEdDSAPublicKey(pubPemBytes)
	case jose.HS256, jose.HS384, jose.HS512:
		return hmac.LoadHMACKey(pubPemBytes)
	case jose.RS256, jose.RS384, jose.RS512, jose.PS256, jose.PS384, jose.PS512:
		return rsax.LoadRSAPublicKey(pubPemBytes)
	case jose.ES256, jose.ES384, jose.ES512:
		return ecdsax.LoadECDSAPublicKey(pubPemBytes)
	default:
		/* 不支持算法 */
		return nil, errors.New("unsupported algorithm")
	}
}

// LoadPrivateKey 加载 PEM 格式的私钥
func LoadPrivateKey(alg jose.SignatureAlgorithm, privPemBytes []byte) (any, error) {
	switch alg {
	case jose.EdDSA:
		return ed25519.LoadEdDSAPrivateKey(privPemBytes)
	case jose.HS256, jose.HS384, jose.HS512:
		return hmac.LoadHMACKey(privPemBytes)
	case jose.RS256, jose.RS384, jose.RS512, jose.PS256, jose.PS384, jose.PS512:
		return rsax.LoadRSAPrivateKey(privPemBytes)
	case jose.ES256, jose.ES384, jose.ES512:
		return ecdsax.LoadECDSAPrivateKey(privPemBytes)
	default:
		/* 不支持算法 */
		return nil, errors.New("unsupported algorithm")
	}
}
